from decimal import Decimal
from currency import currency

valid_units = [
   '%',
   'Days',
   'h',
   'ha',
   'kg',
   'kl',
   'km',
   'kW',
   'l',
   'm',
   'm2',
   'm2.pass',
   'm3',
   'm3.km',
   'mm',
   'MN',
   'MN.m',
   'MPa',
   'No',
   'PC Sum',
   'P/Sum',
   'Sum',
   't'
   ]

# A dict of strings that should be replaced in the units list.  This is to allow
# unicode characters which cannot be easily typed.
_replace_units = {
   'm3' : 'm' + unichr(0x00B3),
   'm2' : 'm' + unichr(0x00B2) }


def toInt(value):
   ''' Like the python function int(), but will always return a value. '''
   try:
      return int(value)
   except ValueError:
      return 0


def formatUnits(value):
   ''' Format value by changing text to unicode as specified in vars.replace_units. '''

   strval = str(value)
   for unit in replace_units.items():
      strval.replace(unit[0], unit[1])

   return strval


def tidy(text):
   '''Replace '_' with ' ', replace first letter with caps.'''
   return text.capitalize().replace('_', ' ')

def untidy(text):
   return text.lower().replace(' ', '_')

# ---------------------------------------------------------------------------
#  Useful support functions
# ---------------------------------------------------------------------------

def move(sequence, oldpsn, newpsn):
   '''Move an item from one position in a mutable sequence to another.

   >>> a = ['m', 'e', 'l', 'o', 'n']
   >>> move(a, 0, 2)
   ['e', 'm', 'l', 'o', 'n']
   >>> move(a, 2, 0)
   ['l', 'e', 'm', 'o', 'n']
   '''
   for psn in [oldpsn, newpsn]:
      psn = (len(sequence) - 1) if psn >= len(sequence) else 0 if psn < 0 else psn

   if oldpsn > newpsn:
      sequence.insert(newpsn, sequence.pop(oldpsn))
   elif oldpsn < newpsn:
      sequence.insert(newpsn - 1, sequence.pop(oldpsn))
   return sequence



def isenum(obj):
   return hasattr(obj, '__class__') and obj.__class__.__name__ == 'EnumClass'

def Enum(*names):
   assert names, 'Empty enums are not supported' # <- Don't like empty enums? Uncomment!

   class EnumClass(object):
      __slots__ = names
      def __iter__(self):        return iter(constants)
      def __len__(self):         return len(constants)
      def __getitem__(self, i):  return constants[i]
      def __repr__(self):        return 'Enum' + str(names)
      def __str__(self):         return 'enum ' + str(constants)

   class EnumValue(object):
      __slots__ = ('__value')
      def __init__(self, value): self.__value = value
      Value = property(lambda self: self.__value)
      EnumType = property(lambda self: EnumType)
      def __hash__(self):        return hash(self.__value)
      def __cmp__(self, other):
         # C fans might want to remove the following assertion
         # to make all enums comparable by ordinal value {;))
         assert self.EnumType is other.EnumType, "Only values from the same enum are comparable"
         return cmp(self.__value, other.__value)
      def __invert__(self):      return constants[maximum - self.__value]
      def __nonzero__(self):     return bool(self.__value)
      def __repr__(self):        return str(names[self.__value])

   maximum = len(names) - 1
   constants = [None] * len(names)
   for i, each in enumerate(names):
      val = EnumValue(i)
      setattr(EnumClass, each, val)
      constants[i] = val
   constants = tuple(constants)
   EnumType = EnumClass()
   return EnumType

import doctest
doctest.testmod()

